package com.fand.stater.interceptor;

import java.util.Date;
import java.util.Enumeration;
import java.util.Map;
import java.util.Objects;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.map.MapUtil;
import com.fand.stater.context.GlobalContextThreadLocal;
import com.fand.stater.context.UserInfoThreadLocal;
import com.fand.stater.handler.SysUserOperateRecordHandler;
import com.fand.stater.model.SysUserDetailDTO;
import com.fand.stater.model.es.SysUserOperateRecord;
import com.fand.common.util.IPUtil;
import com.fand.common.util.JsonUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

/**
 * Author: zhangjiabin
 * Email: javaboyok@163.com
 * CreateDate: 2021/6/26
 * Version: 1.0
 */
@Slf4j
public class UserOperateInterceptor implements HandlerInterceptor {

    private SysUserOperateRecordHandler sysUserOperateRecordHandler;

    public UserOperateInterceptor(SysUserOperateRecordHandler sysUserOperateRecordHandler) {
        this.sysUserOperateRecordHandler = sysUserOperateRecordHandler;
    }

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        SysUserDetailDTO sysUserDetailDTO = UserInfoThreadLocal.get();
        if (Objects.isNull(sysUserDetailDTO)) {
            return true;
        }

        /**
         * 记录用户操作日志
         */

        String sessionId = request.getSession().getId();
        String requestURI = request.getRequestURI();
        String remoteAddr = request.getRemoteAddr();
        Enumeration<String> headerNames = request.getHeaderNames();
        Map<Object, Object> hashMap = MapUtil.newHashMap();
        while (headerNames.hasMoreElements()) {
            String element = headerNames.nextElement();
            String header = request.getHeader(element);
            hashMap.put(element, header);
        }
        String method = request.getMethod();
        String queryString = request.getQueryString();

        SysUserOperateRecord sysUserOperateRecord = SysUserOperateRecord.builder()
                .userId(sysUserDetailDTO.getId())
                .userCode(sysUserDetailDTO.getUsername())
                .userName(sysUserDetailDTO.getRealName())
                .sessionId(sessionId)
                .requestURI(requestURI)
                .remoteAddr(remoteAddr)
                .address(IPUtil.ip2Address(remoteAddr))
                .headerData(JsonUtils.objectToJson(hashMap))
                .method(method)
                .intPut(queryString)
                .time(System.currentTimeMillis())
                .dateTime(DateUtil.formatDateTime(new Date()))
                .build();

        GlobalContextThreadLocal.set("flag", "true");
        GlobalContextThreadLocal.set("startTime", System.currentTimeMillis());
        GlobalContextThreadLocal.set("sysUserOperateRecord", sysUserOperateRecord);
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        String flag = GlobalContextThreadLocal.get("flag");
        if (!"true".equals(flag)) return;
        Long startTime = GlobalContextThreadLocal.get("startTime");
        SysUserOperateRecord sysUserOperateRecord = GlobalContextThreadLocal.get("sysUserOperateRecord");
        sysUserOperateRecord.setCostTime(System.currentTimeMillis() - startTime).setOutPutStatus(response.getStatus());
        GlobalContextThreadLocal.remove();

        sysUserOperateRecordHandler.sendRecord(sysUserOperateRecord);

    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        String flag = GlobalContextThreadLocal.get("flag");
        if (!"true".equals(flag)) return;
        Long startTime = GlobalContextThreadLocal.get("startTime");
        SysUserOperateRecord sysUserOperateRecord = GlobalContextThreadLocal.get("sysUserOperateRecord");
        sysUserOperateRecord.setCostTime(System.currentTimeMillis() - startTime).setOutPutStatus(response.getStatus()).setOutPut(ex == null ? "" : ex.getMessage());
        GlobalContextThreadLocal.remove();

        sysUserOperateRecordHandler.sendRecord(sysUserOperateRecord);

    }
}
